package com.wechat.service.node;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;

import com.swak.annotation.FluxDepend;
import com.swak.boot.ApplicationBooter;
import com.swak.utils.Lists;
import com.wechat.command.Command;
import com.wechat.command.CommandResult;
import com.wechat.config.CmdBean;
import com.wechat.config.RobotBean;
import com.wechat.dto.ChatRoomDTO;
import com.wechat.network.MultiNetwork;
import com.wechat.network.Network;
import com.wechat.network.NetworkHandler;
import com.wechat.network.Networks;
import com.wechat.network.robot.RobotNetwork;
import com.wechat.ser.result.FindResult;
import com.wechat.service.ChatRoomServiceAsync;

/**
 * 节点服务
 * 
 * @author DELL
 */
public class NodeService implements ApplicationBooter, DisposableBean {

	private Network network;

	@FluxDepend
	private ChatRoomServiceAsync chatRoomService;

	@Override
	public void onApplicationEvent(ApplicationContext context) {

		// 处理器
		NetworkHandler exchangeHandler = NetworkHandler.newNetworkHandler();

		// 设置处理器
		exchangeHandler.bind(CmdBean.newCmdRouter());

		// 机器人网络
		List<Network> robots = Lists.newArrayList();
		for (RobotBean bean : RobotBean.robots()) {
			robots.add(new RobotNetwork(bean, exchangeHandler));
		}

		// 远程网络
		Network remote = Networks.New();

		// 返回组合网络处理
		this.network = new MultiNetwork(robots, remote);

		// 绑定服务类，让网络具有访问本地资源的能力
		this.network.bind(this);
	}

	@Override
	public void destroy() throws Exception {
		this.network.close();
	}

	/**
	 * 发送消息
	 * 
	 * @param command
	 * @return
	 */
	public CompletionStage<CommandResult> send(Command command) {
		return this.network.send(command);
	}

	/**
	 * 查询聊天室的信息
	 * 
	 * @param id
	 * @return
	 */
	public CompletableFuture<ChatRoomDTO> getChatRoom(String id) {
		return this.chatRoomService.get(id);
	}

	/**
	 * 查询
	 * 
	 * @param find
	 * @return
	 */
	public CompletionStage<List<FindResult>> find(String find) {
		return this.send(Command.cmdForFindFriend(find)).thenApply(res -> res.result2Object());
	}
}
